﻿using QuestionnaireInvestigation.Data.Data;
using QuestionnaireInvestigation.Data.DTOS;
using QuestionnaireInvestigation.Data.Service;
using QuestionnaireInvestigation.DTOS;
using QuestionnaireInvestigation.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web;
using System.Web.Http;

namespace QuestionnaireInvestigation.Controllers
{
    public class QuestionnaireController : ApiController
    {
        private readonly QuestionnaireService _service = new QuestionnaireService();
        [Authorize]
        [System.Web.Mvc.HttpPost]
        public Questionnaire CreateQuestionnaire(string title)
        {
            try
            {
                return _service.CreateQuestionnaire(title);
            }
            catch
            {
                return null;
            }

        }
        [Authorize]
        [System.Web.Mvc.HttpPost]
        public QuestionnaireDTO AddOptionsToChoiceQuestion([FromBody] RadioDTO radio)
        {
            try
            {
                _service.AddOptionsToChoiceQuestion(radio);
                return GetQuestionnaireById(radio.Qid);
            }
            catch
            {
                return null;
            }
        }
        [Authorize]
        [System.Web.Mvc.HttpGet]
        public QuestionnaireDTO GetQuestionnaireById(int id)
        {
            try
            {
                var questionnaire = _service.GetQuestionnaireById(id);
                QuestionnaireDTO result = new QuestionnaireDTO
                {
                    Qid = questionnaire.Qid,
                    CreateTime = questionnaire.CreateTime.ToShortDateString(),
                    Title = questionnaire.Title
                };
                result.ChoiceQuestions = new List<ChoiceQuestionModel>();
                result.Completions = new List<CompletionModel>();
                foreach (var question in questionnaire.ChoiceQuestions)
                {
                    ChoiceQuestionModel temp = new ChoiceQuestionModel
                    {
                        Qid = question.Qid,
                        QuestionId = question.QuestionId,
                        Title = question.Title,
                        Type = question.Type
                    };
                    temp.Options = new List<OptionModel>();
                    foreach (var opt in question.Options)
                    {
                        OptionModel optTemp = new OptionModel
                        {
                            OptionContent = opt.OptionContent,
                            OptionId = opt.OptionId,
                            QuestionId = opt.QuestionId
                        };
                        temp.Options.Add(optTemp);
                    }
                    result.ChoiceQuestions.Add(temp);
                }
                foreach (var com in questionnaire.Completions)
                {
                    CompletionModel temp = new CompletionModel
                    {
                        CompletionId = com.CompletionId,
                        Qid = com.Qid,
                        Title = com.Title
                    };
                    result.Completions.Add(temp);
                }
                result.ChoiceQuestions = result.ChoiceQuestions.OrderBy(c => c.QuestionId).ToList();
                result.Completions = result.Completions.OrderBy(c => c.CompletionId).ToList();
                return result;
            }
            catch
            {
                return null;
            }

        }
        [Authorize]
        [System.Web.Mvc.HttpPost]
        public QuestionnaireDTO AddCompletionToQuestionnaire([FromBody]CompletionDTO completion)
        {
            try
            {
                _service.AddCompletionToQuestionnaire(completion);
                return GetQuestionnaireById(completion.Qid);
            }
            catch
            {
                return null;
            }
        }

        [System.Web.Mvc.HttpGet]
        public List<QuestionnaireFrontDTO> GetAllQuestionnaire()
        {
            try
            {
                List<QuestionnaireFrontDTO> result = new List<QuestionnaireFrontDTO>();
                var questionnaires = _service.GetAllQuestionnaire();
                foreach (var que in questionnaires)
                {
                    QuestionnaireFrontDTO temp = new QuestionnaireFrontDTO
                    {
                        Qid = que.Qid,
                        Title = que.Title,
                        CreateTime = que.CreateTime.ToLongDateString()
                    };
                    result.Add(temp);
                }
                return result;
            }
            catch
            {
                return null;
            }
        }
        [System.Web.Mvc.HttpGet]
        public QuestionAnswerDTO GetQuestionAnswerById(int id)
        {
            try
            {
                var questionnaire = _service.GetQuestionnaireById(id);
                QuestionAnswerDTO result = new QuestionAnswerDTO
                {
                    Qid = questionnaire.Qid,
                    CreateTime = questionnaire.CreateTime.ToShortDateString(),
                    Title = questionnaire.Title
                };
                result.ChoiceQuestions = new List<ChoiceQuestionModel>();
                result.Completions = new List<CompletionModel>();
                foreach (var question in questionnaire.ChoiceQuestions)
                {
                    ChoiceQuestionModel temp = new ChoiceQuestionModel
                    {
                        Qid = question.Qid,
                        QuestionId = question.QuestionId,
                        Title = question.Title,
                        Type = question.Type
                    };
                    temp.Options = new List<OptionModel>();
                    temp.AnswerOptions = new List<string>();
                    foreach (var opt in question.Options)
                    {
                        OptionModel optTemp = new OptionModel
                        {
                            OptionContent = opt.OptionContent,
                            OptionId = opt.OptionId,
                            QuestionId = opt.QuestionId
                        };
                        temp.Options.Add(optTemp);
                    }
                    result.ChoiceQuestions.Add(temp);
                }
                foreach (var com in questionnaire.Completions)
                {
                    CompletionModel temp = new CompletionModel
                    {
                        CompletionId = com.CompletionId,
                        Qid = com.Qid,
                        Title = com.Title
                    };
                    result.Completions.Add(temp);
                }
                result.ChoiceQuestions = result.ChoiceQuestions.OrderBy(c => c.QuestionId).ToList();
                result.Completions = result.Completions.OrderBy(c => c.CompletionId).ToList();
                return result;
            }
            catch
            {
                return null;
            }
        }
        [System.Web.Mvc.HttpPost]
        public string SubmitAnswer([FromBody]QuestionAnswerDTO answer)
        {
            try
            {
                int answerId = _service.CreateAnswer(GetClientIP(), answer.Qid);
                foreach (var com in answer.Completions)
                {
                    _service.AddCompletionAnswer(answerId, com.Answer, com.CompletionId);
                }
                foreach (var cho in answer.ChoiceQuestions)
                {
                    if (cho.Type == true)
                    {
                        _service.AddRadioAnswer(answerId, cho.QuestionId, cho.AnswerOption);
                    }
                    else
                    {
                        _service.AddMultiselectAnswer(answerId, cho.QuestionId, cho.AnswerOptions);
                    }
                }
                return "Ok";
            }
            catch (Exception e)
            {
                return null;
            }
        }
        [Authorize]
        [HttpGet]
        public List<QuestionnaireFrontDTO> DeleteQuestionnaireById(int id)
        {
            try
            {
                _service.DeleteQuestionnaireById(id);
                return GetAllQuestionnaire();
            }
            catch (Exception e)
            {
                return null;
            }
        }
        [Authorize]
        [System.Web.Mvc.HttpGet]
        public List<AnswerDTO> GetAllAnswer()
        {
            try
            {
                var answers = _service.GetAllAnswer();
                List<AnswerDTO> result = new List<AnswerDTO>();
                foreach (var answer in answers)
                {
                    AnswerDTO temp = new AnswerDTO
                    {
                        AnswerId = answer.AnswerId,
                        IpAddress = answer.IpAddress,
                        CreateTime = answer.CreateTime.ToLongDateString(),
                        QuestionnaireTitle = answer.Questionnaire.Title
                    };
                    result.Add(temp);
                }
                return result;
            }
            catch
            {
                return null;
            }
        }
        [Authorize]
        [HttpPost]
        public AnswerDetailsDTO GetAnswerById(int id)
        {
            try
            {
                var answer = _service.GetAnswerById(id);
                AnswerDetailsDTO result = new AnswerDetailsDTO
                {
                    IpAddress = answer.IpAddress,
                    CreateTime = answer.CreateTime.ToLongDateString(),
                    QuestionnaireTitle = answer.Questionnaire.Title
                };
                result.ChoiceAnswerOptions = new List<ChoiceAnswerOptionModel>();
                result.CompletionAnswerOptions = new List<CompletionAnswerOptionModel>();
                foreach (var choice in answer.ChoiceAnswerOptions)
                {
                    if (result.ChoiceAnswerOptions.SingleOrDefault(c => c.QuestionId == choice.QuestionId) != null)
                    {
                        result.ChoiceAnswerOptions.SingleOrDefault(c => c.QuestionId == choice.QuestionId).AnswerString += " |  " + choice.Option.OptionContent + "  |";
                    }
                    else
                    {
                        ChoiceAnswerOptionModel temp = new ChoiceAnswerOptionModel
                        {

                            QuestionId = choice.QuestionId,
                            Title = choice.ChoiceQuestion.Title,
                            Type = choice.ChoiceQuestion.Type
                        };
                        temp.AnswerString += " |  " + choice.Option.OptionContent+ "   |";
                        temp.Options = new List<OptionModel>();
                        foreach (var option in choice.ChoiceQuestion.Options)
                        {
                            OptionModel opt = new OptionModel
                            {
                                OptionContent = option.OptionContent,
                                OptionId = option.OptionId,
                                QuestionId = option.QuestionId
                            };
                            temp.Options.Add(opt);
                        }

                        result.ChoiceAnswerOptions.Add(temp);
                    }

                }
                foreach (var completion in answer.CompletionAnswerOptions)
                {
                    CompletionAnswerOptionModel temp = new CompletionAnswerOptionModel
                    {
                        AnswerString = completion.AnswerContent,
                        CompletionId = completion.CompletionId,
                        Title = completion.Completion.Title
                    };
                    result.CompletionAnswerOptions.Add(temp);
                }
                return result;
            }
            catch
            {
                return null;
            }
        }
        private static string GetClientIPv4Address()
        {
            string ipv4 = String.Empty;

            foreach (IPAddress ip in Dns.GetHostAddresses(GetClientIP()))
            {
                if (ip.AddressFamily.ToString() == "InterNetwork")
                {
                    ipv4 = ip.ToString();
                    break;
                }
            }

            if (ipv4 != String.Empty)
            {
                return ipv4;
            }
            // 利用 Dns.GetHostEntry 方法，由获取的 IPv6 位址反查 DNS 纪录，
            // 再逐一判断何者为 IPv4 协议，即可转为 IPv4 位址。
            foreach (IPAddress ip in Dns.GetHostEntry(GetClientIP()).AddressList)
            //foreach (IPAddress ip in Dns.GetHostAddresses(Dns.GetHostName()))
            {
                if (ip.AddressFamily.ToString() == "InterNetwork")
                {
                    ipv4 = ip.ToString();
                    break;
                }
            }

            return ipv4;
        }
        private static string GetClientIP()
        {
            if (null == HttpContext.Current.Request.ServerVariables["HTTP_VIA"])
            {
                return HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            }
            else
            {
                return HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            }
        }
    }
}
